home *** CD-ROM | disk | FTP | other *** search
- Path: ocbbs.gen.nz!not-for-mail
- From: steve@hn.ocbbs.gen.nz (Steve Detoni)
- Newsgroups: comp.lang.c
- Subject: Re: Fast Integer Square Root Algorithm
- Date: 28 Jan 1996 11:11:00 +1300
- Message-ID: <4ee7tk$7lk@hn.ocbbs.gen.nz>
- References: <cpruett-2001962141520001@osip74.ionet.net>
- NNTP-Posting-Host: hn.hn.planet.gen.nz
- X-Newsreader: TIN [version 1.2 PL2]
-
- Chris Pruett (cpruett@ionet.net) wrote:
- : Can anyone lend suggestions or give me a reference to a very
- : fast integer square root algorithm?
-
- : 1) Must take square root of unsigned, long integer (32-bit).
- : 2) Accuracy is not terribly important. +/- 100 is acceptable.
-
- : The best I've been able to come up with is Newton's method.
- : Is there something better?
- I asked this question myself, and got a reply, the following code was
- posted me and i'm sure its the fastest method. Doesn't use multiplcation,
- but successive approimatation using bit-shifting. Tis very fast.
-
- #include <stdio.h>
- #include <stdlib.h>
-
- #define BITS_PER_BYTE 8 // Just in case, but it better be even
- #define MYTYPE unsigned long // For generality?
-
-
- void main( int argc, char *argv[])
- {
- MYTYPE question;
- MYTYPE mask;
- MYTYPE answer;
- MYTYPE temp;
- MYTYPE divisor;
- int rotval;
-
- // Just for the purpose of demo
- if (argc == 2)
- {
- question = (MYTYPE)atol( argv[ 1]); // Fudge here for demo
- }
- else
- {
- printf(" Usage %s <number>\n", argv[ 0]);
- exit( 1);
- }
-
- answer = (MYTYPE)0;
- divisor = (MYTYPE)0;
- rotval = ((sizeof(question) * BITS_PER_BYTE) - 2);
- mask = (MYTYPE)3 << rotval;
- temp = (MYTYPE)0;
-
- temp = (temp << 2) + ((question & mask) >> rotval);
- answer = (answer << 1) + (divisor & 1);
- divisor = ((divisor + (divisor & 1))<<1) + 1;
-
- do
- {
- if (divisor > temp)
- {
- divisor--;
- }
- else
- {
- temp -= divisor;
- }
-
- rotval -= 2;
- mask = mask >> 2;
-
- temp = (temp << 2) + ((question & mask) >> rotval);
- answer = (answer << 1) + (divisor & 1);
- divisor = ((divisor + (divisor & 1))<<1) + 1;
-
- } while (mask);
-
- // Round up if required (next bit would be .1 ie >= .5 in decimal
- if (temp >= divisor)
- {
- answer++;
- }
-
- printf("Answer = %ld\n", answer); // Not very general :)
- }
-
- Hope this helps.
- Steve.
-